# -*- coding: utf-8 -*-
# Copyright 2011-2012 MagiCycles.com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import logging

from common import UNITS_DISTANCE, PAGE_SIZE
from models import is_orderable,DBStatistics
from models import DBRide, DBRoute, DBDirections

from people import Activity,SiteUser,Comment

class Route(object):
    """ A route """
    DBTYPE = DBRoute
    Units = UNITS_DISTANCE

    def __init__(self, dbroute=None):
        self.dbroute = dbroute

    def __getattr__(self, name):
        if name == "dbroute":
            return None
        return getattr(self.dbroute, name)

    @property
    def Stats(self):
        return DBStatistics.get_by_route(self.dbroute)

    @property
    def Creator(self):
        return SiteUser(dbuser=self.creator)

    @property
    def Comments(self):
        dbcomments = self.dbroute.dbcomment_set
        return [Comment(dbcomment) for dbcomment in dbcomments if dbcomment is not None and not dbcomment.deleted]

    @property
    def LatestRides(self):
        return Ride.get_by_route(self, pagesize=PAGE_SIZE)[0] # index 1 is cursor

    @property
    def NearbyRoutes(self):
        return Route.search_by_center(self.location, max_results=PAGE_SIZE, max_distance=40000, order="-create_datetime")

    @classmethod
    def create(cls, name, start_addr, end_addr, start_loc, end_loc,
             distance, creator, direction_result, preview_url, route_type="gmap", file_url=""):
        if route_type != "gmap" and not file_url:
            raise Exception("no file url for route that import from KML/GPX")
        dbroute = DBRoute.generate_dbroute(name, start_addr, end_addr, start_loc, end_loc,
                        distance, creator.dbuser, direction_result, preview_url,
                        route_type=route_type, file_url=file_url)
        route = cls(dbroute)
        if dbroute:
            DBStatistics.add_route(creator.dbuser, dbroute)
            Activity.add_route(creator, route)
        return route

    @classmethod
    def get_by_id(cls, id):
        dbroute = DBRoute.get_by_id(id)
        return dbroute and cls(dbroute)

    @classmethod
    def get_by_ids(cls, ids):
        return cls._get_routes_by_dblist(DBRoute.get_by_id(ids))

    @classmethod
    def _get_routes_by_dblist(cls, dbrouteslist):
        return [cls(dbroute) for dbroute in dbrouteslist if dbroute is not None and not dbroute.deleted]

    @classmethod
    def _get_routes_by_query(cls, query, pagesize=50, start_cursor=None):
        query.with_cursor(start_cursor=start_cursor)
        routeslist = [cls(dbroute) for dbroute in query.fetch(pagesize) if dbroute is not None and not dbroute.deleted]
        end_cursor = query.cursor()
        return routeslist,end_cursor

    @classmethod
    def get_all(cls, pagesize=50, start_cursor=None, order='-create_datetime'):
        if not is_orderable(DBRoute, order):
            order = '-create_datetime'
        query = DBRoute.all().order(order)
        return cls._get_routes_by_query(query, pagesize=pagesize, start_cursor=start_cursor)

    @classmethod
    def get_routes_by_user(cls, siteuser, pagesize=50, start_cursor=None, order='-create_datetime'):
        if not is_orderable(DBRoute, order):
            order = '-create_datetime'
        query = siteuser.dbuser.my_routes.order(order)
        return cls._get_routes_by_query(query, pagesize=pagesize, start_cursor=start_cursor)

    @classmethod
    def count_by_center(cls, center, max_distance= 20000):
        return DBRoute.proximity_count(center, max_distance)

    @classmethod
    def search_by_center(cls, center, max_results=1000, max_distance= 20000, order="-distance"):
        if not is_orderable(DBRoute, order):
            order = '-distance'
        #routes_query = DBRoute.all().order(order)
        #results = DBRoute.proximity_fetch(
            #routes_query,
            #center, max_results=max_results, max_distance=max_distance)
        results = DBRoute.proximity_search(center, max_results=max_results, max_distance=max_distance, order=order)
        return cls._get_routes_by_dblist(results)

    @classmethod
    def count_by_bounds(cls, bounds):
        return DBRoute.bounding_box_count(bounds)
    
    @classmethod
    def search_by_bounds(cls, bounds, max_results=1000, order="-distance"):
        if not is_orderable(DBRoute, order):
            order = '-distance'
#        routes_query = DBRoute.all().order(order)
#        results = DBRoute.bounding_box_fetch(
#            routes_query,
#            bounds, max_results=max_results)
        results = DBRoute.bounding_box_search(bounds, max_results=max_results, order=order)
        return cls._get_routes_by_dblist(results)

    @classmethod
    def search_by_text(cls, search_text, pagesize=50, start_cursor=None, order="-distance"):
        if not is_orderable(cls.DBTYPE, order):
            order = '-distance'
        query = cls.DBTYPE.all().order(order).search(search_text, properties=cls.DBTYPE.SearchableProperties()[0])
        return cls._get_routes_by_query(query, pagesize=pagesize, start_cursor=start_cursor)

    @classmethod
    def get_directions_by_id(cls, directionsid):
        dbdirections = DBDirections.get_by_id(directionsid)
        return dbdirections and dbdirections.direction_blod

    def update_attr(self, **attrs):
        for attr,value in attrs.iteritems():
            setattr(self.dbroute, attr, value)
        self.dbroute.save()
        return self

class Ride(object):
    """ A ride """
    DBTYPE = DBRide
    def __init__(self, dbride=None):
        self.dbride = dbride

    def __getattr__(self, name):
        if name == "dbride":
            return None
        return getattr(self.dbride, name)

    @property
    def Rider(self):
        return SiteUser(dbuser=self.rider)

    @classmethod
    def create(cls, bike, rider, route, **kwds):
        dbride = DBRide.new_dbride(bike.dbbike, rider.dbuser, route.dbroute, **kwds)
        ride = cls(dbride)
        if dbride:
            DBStatistics.add_ride(rider.dbuser, dbride)
            Activity.add_ride(rider, ride)
        return ride

    @classmethod
    def get_by_id(cls, id):
        dbride = DBRide.get_by_id(id)
        return dbride and cls(dbride)

    @classmethod
    def get_by_ids(cls, ids):
        dbrideslist = DBRoute.get_by_id(ids)
        return [cls(dbride) for dbride in dbrideslist if dbride is not None and not dbride.deleted]

    @classmethod
    def _get_rides_by_query(cls, query, pagesize=50, start_cursor=None):
        query.with_cursor(start_cursor=start_cursor)
        rideslist = [cls(dbride) for dbride in query.fetch(pagesize) if dbride is not None and not dbride.deleted]
        end_cursor = query.cursor()
        return rideslist,end_cursor

    @classmethod
    def get_all(cls, pagesize=50, start_cursor=None, order='-create_datetime'):
        if not is_orderable(DBRide, order):
            order = '-create_datetime'
        query = DBRide.all().order(order)
        return cls._get_rides_by_query(query, pagesize=pagesize, start_cursor=start_cursor)

    @classmethod
    def get_by_route(cls, route, pagesize=50, start_cursor=None, order='-create_datetime'):
        if not is_orderable(DBRide, order):
            order = '-create_datetime'

        query = route.dbroute.route_rides.order(order) #DBRide.all().filter("route = ", route.dbroute).order(order)
        return cls._get_rides_by_query(query, pagesize=pagesize, start_cursor=start_cursor)

    @classmethod
    def get_by_rider(cls, rider, pagesize=50, start_cursor=None, order='-create_datetime'):
        if not is_orderable(DBRide, order):
            order = '-create_datetime'
            
        query = rider.dbuser.my_rides.order(order) #DBRide.all().filter("rider = ", rider.dbuser).order(order)
        return cls._get_rides_by_query(query, pagesize=pagesize, start_cursor=start_cursor)

    @classmethod
    def get_by_bike(cls, bike, pagesize=50, start_cursor=None, order='-create_datetime'):
        if not is_orderable(DBRide, order):
            order = '-create_datetime'

        query = bike.dbbike.bike_rides.order(order) #DBRide.all().filter("bike = ", bike.dbbike).order(order)
        return cls._get_rides_by_query(query, pagesize=pagesize, start_cursor=start_cursor)


    def update_attr(self, **attrs):
        for attr,value in attrs.iteritems():
            setattr(self.dbride, attr, value)
        self.dbride.save()
        return self


def main():
    pass

if __name__ == '__main__':
    main()
